package com.example.compents.iec.iec104.common;

import io.netty.channel.Channel;
import io.netty.channel.ChannelId;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.util.concurrent.GlobalEventExecutor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

//@Component
//@Slf4j
public class NettyChannelMng {

    //定义一个channle 组，管理所有的channel
    //GlobalEventExecutor.INSTANCE) 是全局的事件执行器，是一个单例
    private static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);

    // 活动的设备id和channelId映射
    private static Map<String, ChannelId> activeDeviceIdChannelIdMapping = new ConcurrentHashMap<>();

    private static Map<ChannelId, String> channelIdDeviceMapping = new ConcurrentHashMap<>();

    synchronized public static void addActiveDeviceChannel(String deviceId, Channel channel) {
        boolean added = channelGroup.add(channel);
        if(added) {
            activeDeviceIdChannelIdMapping.put(deviceId, channel.id());
            channelIdDeviceMapping.put(channel.id(), deviceId);
        }
    }

    synchronized public static void unconnectDevice(String deviceId) {
        activeDeviceIdChannelIdMapping.remove(deviceId);
        Iterator<Map.Entry<ChannelId, String>> iterator = channelIdDeviceMapping.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<ChannelId, String> entry = iterator.next();
            if(Objects.equals(entry.getValue(), deviceId)) {
                iterator.remove();
            }
        }
    }

    synchronized public static Channel getActiveDeviceChannel(String deviceId) {
        ChannelId channelId = activeDeviceIdChannelIdMapping.getOrDefault(deviceId, null);
        if(Objects.isNull(channelId)) {
            return null;
        }

        Channel channel = channelGroup.find(channelId);
        return channel;
    }

    synchronized public static String getDeviceId(Channel channel) {
        String deviceId = channelIdDeviceMapping.getOrDefault(channel.id(), null);
        return deviceId;
    }

    public static List<String> listAddress() {
        List<String> addresses = channelGroup.stream().map(e->e.remoteAddress().toString()).collect(Collectors.toList());
        return addresses;
    }
}
